// 正则库
var regulars = {
    year: {
        regExp: /^(19|20)\d{2}$/,
        message: "只能为年份(四位,1900-2099)"
    },
    number: {
        regExp: /^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$/,
        message: "只能为数字"
    },
    bankNum: {
        regExp: /^\d{16}|\d{19}$/,
        message: "格式错误"
    },
    telephone: {
        regExp: /^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$/,
        message: "格式错误"
    },
    int: {
        regExp: /^[0-9]*$/,
        message: "只能为正整数"
    },
    phone: {
        regExp: /^[1][0-9]{10}$/,
        message: "格式错误"
    },
    allChinese: {
        regExp: /^([\u4E00-\u9FA5]+，?)+$/,
        message: "只能为中文"
    },
    haveChinese: {
        regExp: "[\\u4E00-\\u9FFF]+",
        message: "中含有汉字"
    },
    idCard15: {
        regExp: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/,
        message: "格式错误"
    },
    idCard18: {
        regExp: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$/,
        message: "格式错误"
    },
    url: {
        regExp: /^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+/,
        message: "格式错误"
    },
    email: {
        regExp: /^[-_A-Za-z0-9]+@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,3}$/,
        message: "格式错误"
    },
    Special: {
        regExp: ["~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "{", "}", "[", "]", "(", ")", ":", ";", "'", "|", "\\", "<", ">", "?", "/", "<<", ">>", "||", "//", "administrators", "administrator", "管理员", "系统管理员", "admin", "select", "delete", "update", "insert", "create", "drop", "alter", "trancate"],
        message: "不能包含特殊字符"
    },
    null: {
        regExp: "^[ ]+$",
        message: "不能为空"
    },
};

// 判断对象是否完全一致
const isEqual = function (a, b) {
    if (a === b) {
        return a !== 0 || 1 / a === 1 / b;
    };
    if (a == null || b == null) {
        return a === b;
    };
    var A = Object.prototype.toString.call(a);
    var B = Object.prototype.toString.call(b);
    if (A !== B) {
        return false;
    };
    switch (A) {
        case '[object RegExp]':
        case '[object String]':
            return '' + a === '' + b;
        case '[object Number]':
            if (+a !== +a) {
                return +b !== +b;
            };
            return +a === 0 ? 1 / +a === 1 / b : +a === +b;
        case '[object Date]':
        case '[object Boolean]':
            return +a === +b;
    };
    if (A == '[object Object]') {
        if (JSON.stringify(a) != JSON.stringify(b)) {
            return false;
        };
        return true;
    };
    if (A == '[object Array]') {
        if (a.toString() == b.toString()) {
            return true;
        }
        return false;
    };
};

// 判断是否在数组中，（脱离jquery）
const inArray = function (str, _array) {
    let isInArray = -1;
    for (let i = 0; i < _array.length; i++) {
        const element = _array[i];
        if (isEqual(element, str)) {
            isInArray = i;
            break;
        };
    };
    return isInArray;
};

// 获取对象key值列表
const getKeyArray = function (obj) {
    var _array = [];
    eachObject(obj, function (item, key) {
        _array.push(key);
    });
    return _array;
};

// 将数组以 key 对应属性 为键值 转换为对象，key值默认为ID;
const converArrayToObj = function (_array, key) {
    var obj = {};
    key = key || 'id';

    var canConver = true;
    for (let i = 0; i < _array.length; i++) {
        const element = _array[i];
        if (element.hasOwnProperty(key)) {
            obj[element[key].toString()] = element;
        } else {
            canConver = false;
        }
    };
    if (canConver) {
        return obj;
    } else {
        console.error('对象转换错误 ：未找到对应Key值');
        return obj;
    };
};

// 历遍对象，并执行方法
const eachObject = function (obj, callback) {
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            const element = obj[key];
            var value = callback(element, key);
            if (value === false) {
                break;
            };
        }
    };
};

function test(type, str) {
    var re = new RegExp(regulars[type].regExp);
    return !re.test(str) ? true : false;
};

// 验证用方法集合
var verifyObj = {
    year: {
        event: value => { return test('year', value) },
        message: regulars.year.message,
    },
    number: {
        event: value => { return test('number', value) },
        message: regulars.number.message
    },
    bankNum: {
        event: value => { return test('bankNum', value) },
        message: regulars.bankNum.message
    },
    telephone: {
        event: value => { return test('telephone', value) },
        message: regulars.telephone.message
    },
    int: {
        event: value => { return test('int', value) },
        message: regulars.int.message
    },
    phone: {
        event: value => { return test('phone', value) },
        message: regulars.phone.message
    },
    url: {
        event: value => { return test('url', value) },
        message: regulars.url.message
    },
    email: {
        event: value => { return test('email', value) },
        message: regulars.email.message
    },
    allChinese: {
        event: value => { return test('allChinese', value) },
        message: regulars.allChinese.message
    },
    haveChinese: {
        event: function (str) {
            var re = new RegExp(regulars.haveChinese.regExp);
            return re.test(str) ? true : false;
        },
        message: regulars.haveChinese.message
    },
    notNull: {
        event: function (str) {
            if (str == "" || str == undefined || str == null || str == NaN) return !false;
            var re = new RegExp(regulars.null.regExp);
            return re.test(str);
        },
        message: regulars.null.message
    },
    isSpecial: {
        event: function (str) {
            str = str.toLowerCase();
            for (var i = 0; i < regulars.Special.regExp.length; i++) {
                if (str.indexOf(regulars.Special.regExp[i]) >= 0) {
                    return false;
                }
            }
            return true;
        },
        message: regulars.Special.message
    },
    isIdCard: {
        event: function (str) {
            var re1 = new RegExp(regulars.idCard15.regExp);
            var re2 = new RegExp(regulars.idCard18.regExp);
            return !(re1.test(str) || re2.test(str) ? true : false);
        },
        message: regulars.idCard18.message
    }
};

// 判断变量是否为某一值
const is = function (obj, type) {
    if (type) {
        var result = null;
        var objectString = Object.prototype.toString.call(obj);
        switch (type) {
            case "string":
                result = objectString == "[object String]";
                break;
            case "function":
                result = objectString == "[object Function]";
                break;
            case "array":
                result = objectString == "[object Array]";
                break;
            case "number":
                result = objectString == "[object Number]" && obj === obj;
                break;
            case "date":
                result = objectString == "[object Date]";
                break;
            case "object":
                result = objectString == "[object Object]";
                break;
            case "bool":
                result = objectString == "[object Boolean]";
                break;
            case "regExp":
                result = objectString == "[object RegExp]";
                break;
            case "null":
                result = objectString == "[object Null]";
                break;
            case "undefined":
                result = objectString == "[object Undefined]";
                break;
            case "NaN":
                result = (obj !== obj);
                break;
        };
        return result;
    } else {
        var mold = null;
        var objectString = Object.prototype.toString.call(obj);
        switch (objectString) {
            case "[object String]":
                mold = "string";
                break;
            case "[object Function]":
                mold = "function";
                break;
            case "[object Array]":
                mold = "array";
                break;
            case "[object Number]":
                if (obj !== obj) {
                    mold = "NaN";
                } else {
                    mold = "number"
                };
                break;
            case "[object Date]":
                mold = "date";
                break;
            case "[object Object]":
                mold = "object";
                break;
            case "[object Boolean]":
                mold = "bool";
                break;
            case "[object RegExp]":
                mold = "regExp";
                break;
            case "[object Null]":
                mold = "null";
                break;
            case "[object Undefined]":
                mold = "undefined";
                break;
        };
        return mold;
    };
};

const customLength = function (type, str) {
    var name = type.split('$');
    var length = str.toString().length;
    var nums = parseInt(name[1]);
    if (name[0] == 'les') {
        return !(length > nums) ? '不能小于' + nums + '位' : false;
    } else if (name[0] == 'gre') {
        var nums = parseInt(name[1]);
        return !(length <= nums) ? '不能大于' + nums + '位' : false;
    } else {
        console.error('error => 未找到验证规则:' + type);
    };
};

// 正则验证方法
const jude = function (value, type) {
    var keyArray = getKeyArray(verifyObj);
    if (type.indexOf('$') != -1) {
        return customLength(type, value);
    } else if (inArray(type, keyArray) != -1) {
        var answer = verifyObj[type].event(value);
        return answer ? verifyObj[type].message : false;
    } else {
        console.error('error => 未找到验证规则:' + type);
    };
};

const verifyRule = function (singleRule, value, text) {
    // 返回对象类型
    var ruleType = is(singleRule);
    if (ruleType == 'string') {
        // 当为String类型时,去默认验证方法中寻找
        var result = jude(value, singleRule);
        if (result) {
            return text + result;
        } else {
            return false;
        };
    } else if (ruleType == 'function') {
        // 当为方法类型时,执行方法,并返回验证 (方法通过,返回false,否则返回错误语句);
        var result = singleRule(value);
        if (result) {
            return result;
        } else {
            return false;
        };
    } else if (ruleType == 'object' && singleRule.regExp && is(singleRule.regExp, 'regExp')) {
        // 当对象方法为正则表达式时,直接使用正则表达式进行判断
        var errorText = singleRule.errorText;
        var regular = singleRule.regExp;
        var re = new RegExp(regular);
        if (re.test(value)) {
            return false;
        } else {
            return errorText;
        };
    } else {
        // 其他类型直接跳过,控制台输出错误信息
        console.error('rule模块 : 未识别的判断类型');
        return false;
    };
};

const rules = function (rulesObj, value) {
    var text = rulesObj.text;
    var rulesArray = rulesObj.rules;
    if (!rulesArray) {
        return false;
    };
    // 判断是否为数组
    if (is(rulesArray, 'array')) {
        // 跳过非空验证
        // if ($.inArray("notNull", rulesArray) == -1 && (value == '' || value === null)) {
        //     return false;
        // };
        // 进行循环验证
        var _text = false;
        for (var i = 0; i < rulesArray.length; i++) {
            var element = rulesArray[i];
            var result = verifyRule(element, value, text);
            if (result) {
                _text = result;
                break;
            };
        };
        if (_text) {
            return _text;
        } else {
            return false;
        };
    } else if (is(rulesArray, 'string')) {
        // 进行单条验证
        var result = verifyRule(rulesArray, value, text);
        if (result) {
            return result;
        } else {
            return false;
        };
    } else if (is(rulesArray, 'function')) {
        // 进行单条验证
        var result = verifyRule(rulesArray, value, text);
        if (result) {
            return result;
        } else {
            return false;
        };
    }
};

var clone = function (obj) {
    if (obj === null) return null
    if (typeof obj !== 'object') return obj;
    if (obj.constructor === Date) return new Date(obj);
    var newObj = new obj.constructor();  //保持继承链
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {   //不遍历其原型链上的属性
            var val = obj[key];
            newObj[key] = typeof val === 'object' ? clone(val) : val;
        }
    }
    return newObj;
}

// 添加验证方法
const setJudeRule = function (obj, key) {
    if (verifyObj.hasOwnProperty(key)) {
        console.error('key值重复，不可添加');
        return;
    };
    if (obj.hasOwnProperty('event') && obj.hasOwnProperty('message')) {
        verifyObj[key] = obj;
    } else {
        console.error('添加的验证方法不符合规范');
        return;
    }
};

var getMaxFloor = function (treeData, key) {
    let floor = 0
    let v = this
    let max = 0
    function each(data, floor) {
        data.forEach(e => {
            e.floor = floor
            if (floor > max) {
                max = floor
            }
            if (e.hasOwnProperty(key)) {
                const element = e[key];
                if (element.length > 0) {
                    each(element, floor + 1)
                }
            };
        })
    }
    each(treeData, 1)
    return max
};

var Guid = function () {
    var guid = '';
    for (var i = 1; i <= 32; i++) {
        var n = Math.floor(Math.random() * 16.0).toString(16);
        guid += n;
        if ((i == 8) || (i == 12) || (i == 16) || (i == 20))
            guid += '-';
    }
    return guid;
};

var uuid = function () {
    var uuid = '';
    for (var i = 1; i <= 32; i++) {
        var n = Math.floor(Math.random() * 16.0).toString(16);
        uuid += n;
    }
    return uuid;
};

var fileType = {
    'image': ['webp', 'baidubmp', 'pcx', 'tif', 'gif', 'jpeg', 'jpg', 'tga', 'exif', 'fpx', 'svg', 'pcd', 'dxf', 'ufo', 'png', 'hdri', 'wmf', 'flic', 'emf', 'ico'],
    'psd': ['psd'],
    'cad': ['cdr', 'ai', 'eps', 'raw'],
    'text': ['txt'],
    'html': ['htm', 'html'],
    'mirror': ['iso', 'bin', 'img', 'tao', 'dao', 'cif', 'fcd'],
    'video': ['avi', 'mpeg', 'mpg', 'flv', 'dat', 'ra', 'rm', 'rmvb', 'mov', 'qt', 'asf', 'wmv', 'mkv'],
    'mp3': ['mp3', 'wma', 'mpg', 'wav', 'mv'],
    'zip': ['rar', 'zip', '7z', 'tar', 'xz', 'gz'],
    'xsl': ['xls', 'xlsx'],
    'ppt': ['ppt', 'pptx'],
    'doc': ['doc', 'docx'],
    'pdf': ['pdf'],
    'config': ['conf', 'config', 'ini'],
};

var fileTypeMapping = {};

for (const key in fileType) {
    if (fileType.hasOwnProperty(key)) {
        for (let i = 0; i < fileType[key].length; i++) {
            const element = fileType[key][i];
            fileTypeMapping[element] = key
        };
    }
}

var getSuffixType = function (url) {
    var suffix = url.substring(url.lastIndexOf(".") + 1, url.length);
    if (fileTypeMapping.hasOwnProperty(suffix.toLowerCase())) {
        const element = fileTypeMapping[suffix.toLowerCase()];
        return element;
    } else {
        return 'file'
    }
};

function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) { return pair[1]; }
    }
    return (false);
};

function device(key) {
    var agent = navigator.userAgent.toLowerCase();

    //获取版本号
    var getVersion = function (label) {
        var exp = new RegExp(label + '/([^\\s\\_\\-]+)');
        label = (agent.match(exp) || [])[1];
        return label || false;
    };

    //返回结果集
    var result = {
        os: function () { //底层操作系统
            if (/windows/.test(agent)) {
                return 'windows';
            } else if (/linux/.test(agent)) {
                return 'linux';
            } else if (/iphone|ipod|ipad|ios/.test(agent)) {
                return 'ios';
            } else if (/mac/.test(agent)) {
                return 'mac';
            }
        }(),
        ie: function () { //ie版本
            return (!!window.ActiveXObject || "ActiveXObject" in window) ? (
                (agent.match(/msie\s(\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识
            ) : false;
        }(),
        weixin: getVersion('micromessenger')  //是否微信
    };

    //任意的key
    if (key && !result[key]) {
        result[key] = getVersion(key);
    }

    //移动设备
    result.android = /android/.test(agent);
    result.ios = result.os === 'ios';
    result.mobile = (result.android || result.ios) ? true : false;

    return result;
};


//拆分整数与小数
function splits(tranvalue) {
    var value = new Array('', '');
    var temp = tranvalue.split(".");
    for (var i = 0; i < temp.length; i++) {
        value[i] = temp[i];
    }
    return value;
}

function transformSmallNumber(tranvalue) {
    try {
        tranvalue = tranvalue.toString();
        var i = 1;
        var dw2 = new Array("", "万", "亿");//大单位
        var dw1 = new Array("十", "百", "千");//小单位
        var dw = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");//整数部分用
        //以下是小写转换成大写显示在合计大写的文本框中     
        //分离整数与小数
        var source = splits(tranvalue);
        var num = source[0];
        var dig = source[1];

        //转换整数部分
        var k1 = 0;//计小单位
        var k2 = 0;//计大单位
        var sum = 0;
        var str = "";
        var len = source[0].length;//整数的长度
        for (i = 1; i <= len; i++) {
            var n = source[0].charAt(len - i);//取得某个位数上的数字
            var bn = 0;
            if (len - i - 1 >= 0) {
                bn = source[0].charAt(len - i - 1);//取得某个位数前一位上的数字
            }
            sum = sum + Number(n);
            if (sum != 0) {
                str = dw[Number(n)].concat(str);//取得该数字对应的大写数字，并插入到str字符串的前面
                if (n == '0') sum = 0;
            }
            if (len - i - 1 >= 0) {//在数字范围内
                if (k1 != 3) {//加小单位
                    if (bn != 0) {
                        str = dw1[k1].concat(str);
                    }
                    k1++;
                } else {//不加小单位，加大单位
                    k1 = 0;
                    var temp = str.charAt(0);
                    if (temp == "万" || temp == "亿")//若大单位前没有数字则舍去大单位
                        str = str.substr(1, str.length - 1);
                    str = dw2[k2].concat(str);
                    sum = 0;
                }
            }
            if (k1 == 3)//小单位到千则大单位进一
            { k2++; }
        };
        // //转换小数部分
        var strdig = "";
        if (dig != "") {
            var n = dig.charAt(0);
            if (n != 0) {
                strdig += '点' + dw[Number(n)];//加数字
            }
            var n = dig.charAt(1);
            if (n != 0) {
                strdig += dw[Number(n)];//加数字
            };
            var n = dig.charAt(2);
            if (n != 0) {
                strdig += dw[Number(n)];//加数字
            };
            var n = dig.charAt(3);
            if (n != 0) {
                strdig += dw[Number(n)];//加数字
            };
            var n = dig.charAt(4);
            if (n != 0) {
                strdig += dw[Number(n)];//加数字
            }
        }
        str += strdig;

        str = str.replace(/^一十/, '十');

    } catch (e) {
        return "转换错误";
    }
    return str;
};

// 定义转换函数
function transformBigNumber(tranvalue) {
    try {
        tranvalue = tranvalue.toString();
        var i = 1;
        var dw2 = new Array("", "万", "亿");//大单位
        var dw1 = new Array("拾", "佰", "仟");//小单位
        var dw = new Array("零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖");//整数部分用
        //以下是小写转换成大写显示在合计大写的文本框中     
        //分离整数与小数
        var source = splits(tranvalue);
        var num = source[0];
        var dig = source[1];

        //转换整数部分
        var k1 = 0;//计小单位
        var k2 = 0;//计大单位
        var sum = 0;
        var str = "";
        var len = source[0].length;//整数的长度
        for (i = 1; i <= len; i++) {
            var n = source[0].charAt(len - i);//取得某个位数上的数字
            var bn = 0;
            if (len - i - 1 >= 0) {
                bn = source[0].charAt(len - i - 1);//取得某个位数前一位上的数字
            }
            sum = sum + Number(n);
            if (sum != 0) {
                str = dw[Number(n)].concat(str);//取得该数字对应的大写数字，并插入到str字符串的前面
                if (n == '0') sum = 0;
            }
            if (len - i - 1 >= 0) {//在数字范围内
                if (k1 != 3) {//加小单位
                    if (bn != 0) {
                        str = dw1[k1].concat(str);
                    }
                    k1++;
                } else {//不加小单位，加大单位
                    k1 = 0;
                    var temp = str.charAt(0);
                    if (temp == "万" || temp == "亿")//若大单位前没有数字则舍去大单位
                        str = str.substr(1, str.length - 1);
                    str = dw2[k2].concat(str);
                    sum = 0;
                }
            }
            if (k1 == 3)//小单位到千则大单位进一
            { k2++; }
        }

        //转换小数部分
        var strdig = "";
        if (dig != "") {
            var n = dig.charAt(0);
            if (n != 0) {
                strdig += dw[Number(n)] + "角";//加数字
            }
            var n = dig.charAt(1);
            if (n != 0) {
                strdig += dw[Number(n)] + "分";//加数字
            }
        }
        str += "元" + strdig;
    } catch (e) {
        return "0元";
    }
    return str;
}



export default {
    device,
    rules,
    uuid,
    Guid,
    inArray,
    getKeyArray,
    eachObject,
    is,
    jude,
    isEqual,
    setJudeRule,
    converArrayToObj,
    clone,
    getMaxFloor,
    getSuffixType,// 获取文件后缀名
    getQueryVariable,
    transformBigNumber,
    transformSmallNumber
}